package com.biubiushop.socket.netty;

import cn.hutool.log.Log;
import cn.hutool.log.LogFactory;
import com.biubiushop.repository.IEquipmentRepository;
import com.biubiushop.repository.IOrdersRepository;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.core.Ordered;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @author chenjia
 * @date 2019/10/22
 **/
@Component
public class NettyServer implements ApplicationRunner, Ordered {

    public ConcurrentHashMap<String, Channel> channelMap = new ConcurrentHashMap<>(16);

    private static final Log log = LogFactory.get();

    @Resource
    ThreadPoolTaskExecutor threadPoolTaskExecutor;

    @Resource
    IEquipmentRepository equipmentRepository;

    @Resource
    IOrdersRepository ordersRepository;

    @Resource
    StringRedisTemplate stringRedisTemplate;


    public void startServer() {

        //1.定义server启动类
        ServerBootstrap serverBootstrap = new ServerBootstrap();

        //2.定义工作组:boss分发请求给各个worker:boss负责监听端口请求，worker负责处理请求（读写）
        EventLoopGroup boss = new NioEventLoopGroup();
        EventLoopGroup worker = new NioEventLoopGroup();

        //3.定义工作组
        serverBootstrap.group(boss, worker);

        //4.设置通道channel
        serverBootstrap.channel(NioServerSocketChannel.class);

        //5.添加handler，管道中的处理器，通过ChannelInitializer来构造
        serverBootstrap.childHandler(new ServerFilter(threadPoolTaskExecutor, channelMap, equipmentRepository, ordersRepository, stringRedisTemplate));

        //6.设置参数
        //设置参数，TCP参数
        serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);         //连接缓冲池的大小
        serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);//维持链接的活跃，清除死链接
        serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);//关闭延迟发送

        //7.绑定ip和port
        try {
            ChannelFuture channelFuture = serverBootstrap.bind(8888).sync();//Future模式的channel对象
            //7.5.监听关闭
            channelFuture.channel().closeFuture().sync();  //等待服务关闭，关闭后应该释放资源
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            //8.优雅的关闭资源
            boss.shutdownGracefully();
            worker.shutdownGracefully();
        }


    }

    @Override
    public void run(ApplicationArguments args) {
        log.info("..................共享纸巾Netty服务端启动..................");
        startServer();
        log.info("..................共享纸巾Netty服务端已关闭..................");
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
